//ArquivoBinarioAutomovelDAO.java
// classe de DAO do automovel para arquivo binário
// Observação: um registro de automovel possui 340 bytes
package dao;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import modelo.Automovel;
import modelo.Motorista;

/**
 * @author Diego Heusser
 * @author Eder Schramm
 */
public class ArquivoBinarioAutomovelDAO extends ArquivoBinarioDAO implements AutomovelDAO {

    @Override
    public boolean inserir(Automovel umAutomovel) {
        try {
            File file = new File(automovel_url, nome_automovel);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            RegistroAutomovel registro = new RegistroAutomovel();
            if (inicio_automovel == -1) {
                inicio_automovel = qtdArquivos(raf, registro.getTamanho());
                registro.escreve(raf, inicio_automovel, -1, umAutomovel);
                atualizaConfiguracao();
            } else {
                int identificador = qtdArquivos(raf, registro.getTamanho());
                raf.seek((identificador * registro.getTamanho()) - 4);
                raf.writeInt(identificador);
                registro.escreve(raf, identificador, -1, umAutomovel);
            }
            raf.close();
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    @Override
    public boolean alterar(Automovel umAutomovel) {
        try {
            File file = new File(automovel_url, nome_automovel);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Motorista> lista = new ArrayList<>();

            RegistroAutomovel registro = new RegistroAutomovel();
            raf.seek(inicio_automovel * registro.getTamanho());
            do {
                registro.ler(raf);
                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getId() != umAutomovel.getId());
            raf.seek(registro.getIdentificador() * registro.getTamanho());
            registro.escreve(raf, registro.getIdentificador(), registro.getProximo(), umAutomovel);
            raf.close();
            return true;
        } catch (IOException ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean remover(int id) {
        try {
            if (inicio_automovel == -1) {
                return false;
            }
            File file = new File(automovel_url, nome_automovel);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");

            RegistroAutomovel registro = new RegistroAutomovel();
            raf.seek(inicio_automovel * registro.getTamanho());
            do {
                registro.ler(raf);
                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getId() != id);

            int identificador = registro.getIdentificador();
            int proximo = registro.getProximo();

            if (identificador == inicio_automovel) {
                inicio_automovel = proximo;
                atualizaConfiguracao();
                return true;
            }

            raf.seek(inicio_automovel * registro.getTamanho());
            registro.ler(raf);
            while (raf.getFilePointer() < raf.length()) {
                if (registro.getProximo() == identificador) {
                    raf.seek(raf.getFilePointer() - 4);
                    raf.writeInt(proximo);
                    return true;
                }
                raf.seek(registro.getProximo() * registro.getTamanho());
            }

            return false;
        } catch (IOException ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public List<Automovel> listar() {
        try {
            if (inicio_automovel == -1) {
                return new ArrayList<>();
            }
            File file = new File(automovel_url, nome_automovel);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Automovel> lista = new ArrayList<>();

            RegistroAutomovel registro = new RegistroAutomovel();
            raf.seek(inicio_automovel * registro.getTamanho());
            do {
                registro.ler(raf);

                Automovel umAutomovel = new Automovel();
                umAutomovel.setId(registro.getId());
                umAutomovel.setAno(registro.getAno());
                umAutomovel.setCombustivel(registro.getCombustivel());
                umAutomovel.setCor(registro.getCor());
                umAutomovel.setFabricante(registro.getFabricante());
                umAutomovel.setModelo(registro.getModelo());

                ArquivoBinarioMotoristaDAO dao = new ArquivoBinarioMotoristaDAO();
                Motorista umMotorista = dao.listar(registro.getMotoritaId());

                umAutomovel.setUmMotorista(umMotorista);

                lista.add(umAutomovel);

                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getProximo() != -1);

            return lista;
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public List<Automovel> listarFisico() {
        try {
            File file = new File(automovel_url, nome_automovel);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Automovel> lista = new ArrayList<>();
            RegistroAutomovel registro = new RegistroAutomovel();
            while (raf.getFilePointer() < raf.length()) {
                registro.ler(raf);
                Automovel umAutomovel = new Automovel();
                umAutomovel.setAno(registro.getAno());
                umAutomovel.setCombustivel(registro.getCombustivel());
                umAutomovel.setCor(registro.getCor());
                umAutomovel.setFabricante(registro.getFabricante());
                umAutomovel.setId(registro.getId());
                umAutomovel.setModelo(registro.getModelo());
                umAutomovel.setUmMotorista(new dao.ArquivoBinarioMotoristaDAO().
                        listarFisico(registro.getMotoritaId()));
                
                lista.add(umAutomovel);
            }
            return lista;
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public List<Automovel> listar(String motorista) {
        try {
            if (inicio_automovel == -1) {
                return new ArrayList<>();
            }
            File file = new File(automovel_url, nome_automovel);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Automovel> lista = new ArrayList<>();
            
            List<Motorista> motoristas = new dao.ArquivoBinarioMotoristaDAO().listar(motorista);
            RegistroAutomovel registro = new RegistroAutomovel();
            
            for (Motorista umMotorista : motoristas) {
                raf.seek(inicio_automovel * registro.getTamanho());
                do {
                    registro.ler(raf);
                    if (registro.getMotoritaId() == umMotorista.getId()) {
                        Automovel umAutomovel = new Automovel();
                        umAutomovel.setAno(registro.getAno());
                        umAutomovel.setCombustivel(registro.getCombustivel());
                        umAutomovel.setCor(registro.getCor());
                        umAutomovel.setFabricante(registro.getFabricante());
                        umAutomovel.setId(registro.getId());
                        umAutomovel.setModelo(registro.getModelo());
                        umAutomovel.setUmMotorista(umMotorista);
                        lista.add(umAutomovel);
                    }
                    if (registro.getProximo() != -1){
                        raf.seek(registro.getProximo()*registro.getTamanho());
                    }
                } while (registro.getProximo() != -1);
            }
            return lista;
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean idValido(int id) {
        try {
            File file = new File(automovel_url, nome_automovel);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            if (inicio_automovel == -1) {
                raf.close();
                return true;
            }
            RegistroAutomovel registro = new RegistroAutomovel();
            raf.seek(inicio_automovel * registro.getTamanho());
            do {
                registro.ler(raf);
                if (registro.getId() == id) {
                    raf.close();
                    return false;
                }
                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getProximo() != -1);
            raf.close();
            return true;
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
            return false;
        } catch (IOException ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean apagarDados() {
        try {
            inicio_automovel = -1;
            atualizaConfiguracao();
            return true;
        } catch (Exception ex ) {
            return false;
        }
    }

    @Override
    public boolean criarTabela() throws Exception {
        throw new UnsupportedOperationException("Não é possível criar tabela com Arquivo Binário");
    }

}
